package cc.shacocloud.mirage.core;

import cc.shacocloud.mirage.bean.BeanFactory;
import cc.shacocloud.mirage.env.Environment;
import io.netty.channel.EventLoopGroup;
import io.vertx.core.*;
import io.vertx.core.datagram.DatagramSocket;
import io.vertx.core.datagram.DatagramSocketOptions;
import io.vertx.core.dns.DnsClient;
import io.vertx.core.dns.DnsClientOptions;
import io.vertx.core.eventbus.EventBus;
import io.vertx.core.file.FileSystem;
import io.vertx.core.http.HttpClient;
import io.vertx.core.http.HttpClientOptions;
import io.vertx.core.http.HttpServer;
import io.vertx.core.http.HttpServerOptions;
import io.vertx.core.net.NetClient;
import io.vertx.core.net.NetClientOptions;
import io.vertx.core.net.NetServer;
import io.vertx.core.net.NetServerOptions;
import io.vertx.core.shareddata.SharedData;
import io.vertx.core.spi.VerticleFactory;
import org.jetbrains.annotations.NotNull;

import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

/**
 * 应用上下文接口
 * <p>
 * 是 对象工厂，环境配置，应用事件的一个总和
 *
 * @author 思追(shaco)
 */
public interface ApplicationContext extends Vertx, BeanFactory, Environment, ApplicationEventMulticaster {
    
    /**
     * 默认的应用名称
     */
    String DEFAULT_APPLICATION_NAME = "mirage";
    
    /**
     * 默认的应用名称键
     */
    String APPLICATION_NAME_KEY = "mirage.application.name";
    
    /**
     * 获取当前应用的 Vertx 对象
     */
    default Vertx getVertx() {
        return getBean(Vertx.class);
    }
    
    /**
     * 应用名称
     */
    default String getApplicationName() {
        return getProperty(APPLICATION_NAME_KEY, String.class, DEFAULT_APPLICATION_NAME);
    }
    
    /**
     * 获取应用启动的时间戳
     */
    long getStartupDate();
    
    /**
     * 获取当前应用内置的对象工厂
     */
    @NotNull
    BeanFactory getBeanFactory();
    
    
    // -------------- 委托
    
    @Override
    default Context getOrCreateContext() {
        return getVertx().getOrCreateContext();
    }
    
    @Override
    default NetServer createNetServer(NetServerOptions options) {
        return getVertx().createNetServer(options);
    }
    
    @Override
    default NetServer createNetServer() {
        return getVertx().createNetServer();
    }
    
    @Override
    default NetClient createNetClient(NetClientOptions options) {
        return getVertx().createNetClient(options);
    }
    
    @Override
    default NetClient createNetClient() {
        return getVertx().createNetClient();
    }
    
    @Override
    default HttpServer createHttpServer(HttpServerOptions options) {
        return getVertx().createHttpServer(options);
    }
    
    @Override
    default HttpServer createHttpServer() {
        return getVertx().createHttpServer();
    }
    
    @Override
    default HttpClient createHttpClient(HttpClientOptions options) {
        return getVertx().createHttpClient(options);
    }
    
    @Override
    default HttpClient createHttpClient() {
        return getVertx().createHttpClient();
    }
    
    @Override
    default DatagramSocket createDatagramSocket(DatagramSocketOptions options) {
        return getVertx().createDatagramSocket(options);
    }
    
    @Override
    default DatagramSocket createDatagramSocket() {
        return getVertx().createDatagramSocket();
    }
    
    @Override
    default FileSystem fileSystem() {
        return getVertx().fileSystem();
    }
    
    @Override
    default EventBus eventBus() {
        return getVertx().eventBus();
    }
    
    @Override
    default DnsClient createDnsClient(int port, String host) {
        return getVertx().createDnsClient(port, host);
    }
    
    @Override
    default DnsClient createDnsClient() {
        return getVertx().createDnsClient();
    }
    
    @Override
    default DnsClient createDnsClient(DnsClientOptions options) {
        return getVertx().createDnsClient(options);
    }
    
    @Override
    default SharedData sharedData() {
        return getVertx().sharedData();
    }
    
    @Override
    default long setTimer(long delay, Handler<Long> handler) {
        return getVertx().setTimer(delay, handler);
    }
    
    @Override
    default TimeoutStream timerStream(long delay) {
        return getVertx().timerStream(delay);
    }
    
    @Override
    default long setPeriodic(long delay, Handler<Long> handler) {
        return getVertx().setPeriodic(delay, handler);
    }
    
    @Override
    default long setPeriodic(long initialDelay, long delay, Handler<Long> handler) {
        return getVertx().setPeriodic(initialDelay, delay, handler);
    }
    
    @Override
    default TimeoutStream periodicStream(long delay) {
        return getVertx().periodicStream(delay);
    }
    
    @Override
    default TimeoutStream periodicStream(long initialDelay, long delay) {
        return getVertx().periodicStream(initialDelay, delay);
    }
    
    @Override
    default boolean cancelTimer(long id) {
        return getVertx().cancelTimer(id);
    }
    
    @Override
    default void runOnContext(Handler<Void> action) {
        getVertx().runOnContext(action);
    }
    
    @Override
    default Future<Void> close() {
        return getVertx().close();
    }
    
    @Override
    default void close(Handler<AsyncResult<Void>> completionHandler) {
        getVertx().close(completionHandler);
    }
    
    @Override
    default Future<String> deployVerticle(Verticle verticle) {
        return getVertx().deployVerticle(verticle);
    }
    
    @Override
    default void deployVerticle(Verticle verticle, Handler<AsyncResult<String>> completionHandler) {
        getVertx().deployVerticle(verticle, completionHandler);
    }
    
    @Override
    default Future<String> deployVerticle(Verticle verticle, DeploymentOptions options) {
        return getVertx().deployVerticle(verticle, options);
    }
    
    @Override
    default Future<String> deployVerticle(Class<? extends Verticle> verticleClass, DeploymentOptions options) {
        return getVertx().deployVerticle(verticleClass, options);
    }
    
    @Override
    default Future<String> deployVerticle(Supplier<Verticle> verticleSupplier, DeploymentOptions options) {
        return getVertx().deployVerticle(verticleSupplier, options);
    }
    
    @Override
    default void deployVerticle(Verticle verticle, DeploymentOptions options, Handler<AsyncResult<String>> completionHandler) {
        getVertx().deployVerticle(verticle, options, completionHandler);
    }
    
    @Override
    default void deployVerticle(Class<? extends Verticle> verticleClass, DeploymentOptions options, Handler<AsyncResult<String>> completionHandler) {
        getVertx().deployVerticle(verticleClass, options, completionHandler);
    }
    
    @Override
    default void deployVerticle(Supplier<Verticle> verticleSupplier, DeploymentOptions options, Handler<AsyncResult<String>> completionHandler) {
        getVertx().deployVerticle(verticleSupplier, options, completionHandler);
    }
    
    @Override
    default Future<String> deployVerticle(String name) {
        return getVertx().deployVerticle(name);
    }
    
    @Override
    default void deployVerticle(String name, Handler<AsyncResult<String>> completionHandler) {
        getVertx().deployVerticle(name, completionHandler);
    }
    
    @Override
    default Future<String> deployVerticle(String name, DeploymentOptions options) {
        return getVertx().deployVerticle(name, options);
    }
    
    @Override
    default void deployVerticle(String name, DeploymentOptions options, Handler<AsyncResult<String>> completionHandler) {
        getVertx().deployVerticle(name, options, completionHandler);
    }
    
    @Override
    default Future<Void> undeploy(String deploymentID) {
        return getVertx().undeploy(deploymentID);
    }
    
    @Override
    default void undeploy(String deploymentID, Handler<AsyncResult<Void>> completionHandler) {
        getVertx().undeploy(deploymentID, completionHandler);
    }
    
    @Override
    default Set<String> deploymentIDs() {
        return getVertx().deploymentIDs();
    }
    
    @Override
    default void registerVerticleFactory(VerticleFactory factory) {
        getVertx().registerVerticleFactory(factory);
    }
    
    @Override
    default void unregisterVerticleFactory(VerticleFactory factory) {
        getVertx().unregisterVerticleFactory(factory);
    }
    
    @Override
    default Set<VerticleFactory> verticleFactories() {
        return getVertx().verticleFactories();
    }
    
    @Override
    default boolean isClustered() {
        return getVertx().isClustered();
    }
    
    @Override
    default <T> void executeBlocking(Handler<Promise<T>> blockingCodeHandler, boolean ordered, Handler<AsyncResult<T>> asyncResultHandler) {
        getVertx().executeBlocking(blockingCodeHandler, ordered, asyncResultHandler);
    }
    
    @Override
    default <T> void executeBlocking(Handler<Promise<T>> blockingCodeHandler, Handler<AsyncResult<T>> asyncResultHandler) {
        getVertx().executeBlocking(blockingCodeHandler, asyncResultHandler);
    }
    
    @Override
    default <T> Future<T> executeBlocking(Handler<Promise<T>> blockingCodeHandler, boolean ordered) {
        return getVertx().executeBlocking(blockingCodeHandler, ordered);
    }
    
    @Override
    default <T> Future<T> executeBlocking(Handler<Promise<T>> blockingCodeHandler) {
        return getVertx().executeBlocking(blockingCodeHandler);
    }
    
    @Override
    default EventLoopGroup nettyEventLoopGroup() {
        return getVertx().nettyEventLoopGroup();
    }
    
    @Override
    default WorkerExecutor createSharedWorkerExecutor(String name) {
        return getVertx().createSharedWorkerExecutor(name);
    }
    
    @Override
    default WorkerExecutor createSharedWorkerExecutor(String name, int poolSize) {
        return getVertx().createSharedWorkerExecutor(name, poolSize);
    }
    
    @Override
    default WorkerExecutor createSharedWorkerExecutor(String name, int poolSize, long maxExecuteTime) {
        return getVertx().createSharedWorkerExecutor(name, poolSize, maxExecuteTime);
    }
    
    @Override
    default WorkerExecutor createSharedWorkerExecutor(String name, int poolSize, long maxExecuteTime, TimeUnit maxExecuteTimeUnit) {
        return getVertx().createSharedWorkerExecutor(name, poolSize, maxExecuteTime, maxExecuteTimeUnit);
    }
    
    @Override
    default boolean isNativeTransportEnabled() {
        return getVertx().isNativeTransportEnabled();
    }
    
    @Override
    default Vertx exceptionHandler(Handler<Throwable> handler) {
        return getVertx().exceptionHandler(handler);
    }
    
    @Override
    default Handler<Throwable> exceptionHandler() {
        return getVertx().exceptionHandler();
    }
    
    @Override
    default boolean isMetricsEnabled() {
        return getVertx().isMetricsEnabled();
    }
    
    @Override
    default Throwable unavailableNativeTransportCause() {
        return getVertx().unavailableNativeTransportCause();
    }
}
